from micropython import const  # 引入常量

DATETIME_REG = const(0) # 日期的地址是从0x00-0x06
CHIP_HALT    = const(128)

class DS1307(object):
    def __init__(self, i2c, addr=0x68):# 定义一个DS1307的类
        self.i2c = i2c
        self.addr = addr
        self.weekday_start = 1
        self._halt = False  # False时振荡器启动，True时振荡器关闭

    def _dec2bcd(self, value):# 将十进制转换为二进制编码十进制（BCD）格式
        return (value // 10) << 4 | (value % 10)

    def _bcd2dec(self, value):# 将二进制编码十进制（BCD）格式转换为十进制
        return ((value >> 4) * 10) + (value & 0x0F)

    def datetime(self, datetime=None):# 设定或获得时间
        if datetime is None:# 设定时间
            buf = self.i2c.readfrom_mem(self.addr, DATETIME_REG, 7)# 从寄存器中获得时间数据
            return (
                self._bcd2dec(buf[6]) + 2000, # year
                self._bcd2dec(buf[5]), # months
                self._bcd2dec(buf[4]), # days
                self._bcd2dec(buf[3] - self.weekday_start), # weekday
                self._bcd2dec(buf[2]), # hours
                self._bcd2dec(buf[1]), # minutes
                self._bcd2dec(buf[0] & 0x7F), # seconds
                0 # subseconds
            )
        buf = bytearray(7)
        buf[0] = self._dec2bcd(datetime[6]) & 0x7F # second,msb=CH,1=halt,0=go
        buf[1] = self._dec2bcd(datetime[5]) # minute
        buf[2] = self._dec2bcd(datetime[4]) # hour
        buf[3] = self._dec2bcd(datetime[3] + self.weekday_start) # weekday
        buf[4] = self._dec2bcd(datetime[2]) # day
        buf[5] = self._dec2bcd(datetime[1]) # month
        buf[6] = self._dec2bcd(datetime[0] - 2000) # year
        if (self._halt):
            buf[0] |= (1 << 7)
        self.i2c.writeto_mem(self.addr, DATETIME_REG, buf)# 向寄存器内写入时间数据

    def halt(self, val=None):# 通电、断电或检查状态
        if val is None:
            return self._halt
        reg = self.i2c.readfrom_mem(self.addr, DATETIME_REG, 1)[0]
        if val:
            reg |= CHIP_HALT
        else:
            reg &= ~CHIP_HALT
        self._halt = bool(val)
        self.i2c.writeto_mem(self.addr, DATETIME_REG, bytearray([reg]))